<?php
/**
 * Created by PhpStorm.
 * User: jaylen
 * Date: 2020-04-09
 * Time: 16:29
 */

namespace app\common\validate;


use think\Validate;

class BaseValidate extends Validate
{
    /**
     * 检查对应的参数是否为正整数
     * @param $value
     * @param string $rule
     * @param string $data
     * @return bool
     */
    protected function isPositiveInteger($value,$rule = ''
        ,$data = '') {
        if (is_numeric($value) && is_int($value + 0) && ($value + 0) > 0){
            return true;
        }else{
            return false;
        }
    }

    /**
     * 检查使用逗号分隔的id保存多个id的字符串是否正确
     * @param $value
     * @param string $rule
     * @param string $data
     * @param string $field
     * @return bool
     */
    protected function checkIDs($value,$rule = ''
        ,$data = '',$field = ''){
        if (!is_array($value)) {
            $value = explode(',',$value);
        }

        if (empty($value)){
            return false;
        }

        foreach ($value as $id){
            if (!$this->isPositiveInteger($id)){
                return false;
            }
        }

        return true;
    }

    /**
     * 检查所有参数是否符合全部为只能是汉字、字母、数字和下划线_及破折号-
     * @param $value
     * @param string $rule
     * @param string $data
     * @param string $field
     * @return bool
     */
    protected function checkAllParamIsChsDash($value,$rule = ''
        ,$data = '',$field = '')
    {
        return $this->checkAllParamWithRegex($value,'/^[\x{4e00}-\x{9fa5}a-zA-Z0-9\_\-]+$/u');
    }

    /**
     * 检查所有参数是否符合全部为字母和数字，下划线_及破折号-
     * @param $value
     * @param string $rule
     * @param string $data
     * @param string $field
     * @return bool
     */
    protected function checkAllParamIsAlphaDash($value,$rule = ''
        ,$data = '',$field = '')
    {
        return $this->checkAllParamWithRegex($value,'/^[A-Za-z0-9\-\_]+$/');
    }

    /**
     * 检查所有参数是否符合全部为为纯数字
     * @param $value
     * @param string $rule
     * @param string $data
     * @param string $field
     * @return bool
     */
    protected function checkAllParamIsNumber($value,$rule = ''
        ,$data = '',$field = '')
    {
        // 如果需要验证的值不是数组放回false
        if (!is_array($value)) {
            return false;
        }

        foreach ($value as $item) {
            if (!ctype_digit((string) $item)) {
                return false;
            }
        }

        return true;
    }

    /**
     * 检查所有参数是否符合全部不为空
     * @param $value
     * @param string $rule
     * @param string $data
     * @param string $field
     * @return bool
     */
    protected function checkAllParamRequire($value,$rule = ''
        ,$data = '',$field = '')
    {
        // 如果需要验证的值不是数组放回false
        if (!is_array($value)) {
            return false;
        }

        foreach ($value as $item) {
            if (empty($item) || '0' == $item) {
                return false;
            }
        }

        return true;
    }

    /**
     * 检查所有参数是否符合最大长度比规则规定的小
     * @param $value
     * @param string $rule
     * @param string $data
     * @param string $field
     * @return bool
     */
    protected function checkAllParamMax($value,$rule = ''
        ,$data = '',$field = '')
    {
        // 如果需要验证的值不是数组放回false
        if (!is_array($value)) {
            return false;
        }

        foreach ($value as $item) {
            if (!$this->max($item,$rule)) {
                return false;
            }
        }

        return true;
    }

    /**
     * 检查所有参数是否符合在两个值之间
     * @param $value
     * @param string $rule
     * @param string $data
     * @param string $field
     * @return bool
     */
    protected function checkAllParamBetween($value,$rule = ''
        ,$data = '',$field = '')
    {
        // 如果需要验证的值不是数组放回false
        if (!is_array($value)) {
            return false;
        }

        foreach ($value as $item) {
            if (!$this->between($item,$rule)) {
                return false;
            }
        }

        return true;
    }

    /**
     * 检验数组中的所有参数是否符合对应的正则表达式
     * @param $value
     * @param $regex
     * @return bool
     */
    protected function checkAllParamWithRegex($value,$regex)
    {
        // 如果需要验证的值不是数组放回false
        if (!is_array($value)) {
            return false;
        }

        // 遍历循环，如果不符合规则直接返回false
        // is_scalar — 检测变量是否是一个标量 标量变量是指那些包含了 integer、float、string 或 boolean的变量，而 array、object 和 resource 则不是标量。
        foreach ($value as $item) {
            if (!(is_scalar($item) && 1 === preg_match($regex, (string) $item))) {
                return false;
            }
        }

        return true;
    }



    /**
     * 验证是否唯一
     * @access public
     * @param mixed $value 字段值
     * @param mixed $rule 验证规则 格式：数据表,字段名,排除ID,主键名
     * @param array $data 数据
     * @param string $field 验证字段名
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function unique($value, $rule, array $data = [], string $field = ''): bool
    {
        if (is_string($rule)) {
            $rule = explode(',', $rule);
        }

        if (false !== strpos($rule[0], '\\')) {
            // 指定模型类
            $db = new $rule[0];
        } else {
            $db = $this->db->name($rule[0]);
        }

        $key = $rule[1] ?? $field;
        $map = [];

        if (strpos($key, '^')) {
            // 支持多个字段验证
            $fields = explode('^', $key);
            foreach ($fields as $key) {
                if (isset($data[$key])) {
                    $map[] = [$key, '=', $data[$key]];
                }
            }
        } elseif (strpos($key, '=')) {
            // 支持复杂验证条件
            $fields = explode('&', $key);
            $map_arr=[];
            foreach ($fields as $key) {
                $str_map=explode('=', $key);
                $map[] = [$str_map[0], '=', $str_map[1]];
                $map_arr[]=$str_map[0];
            }
            if(!in_array($field, $map_arr)){
                $map[]=[$field,'=',$data[$field]];
            }
        } elseif (isset($data[$field])) {
            $map[] = [$key, '=', $data[$field]];
        } else {
            $map = [];
        }

        $pk = !empty($rule[3]) ? $rule[3] : $db->getPk();

        if (is_string($pk)) {
            if (isset($rule[2])) {
                $map[] = [$pk, '<>', $rule[2]];
            } elseif (isset($data[$pk])) {
                $map[] = [$pk, '<>', $data[$pk]];
            }
        }

        if ($db->where($map)->field($pk)->find()) {
            return false;
        }

        return true;
    }
}